var express = require("express");
var router = express.Router();

const { Course, Category, User, Chapter } = require("../../models");
// 复杂查询
const { Op } = require("sequelize");
// 自定义异常
const { NotFound, Conflict } = require("http-errors");
// 自定义响应
const { success, failure } = require("../../utils/responses");
const { getKeysByPattern, delKey } = require("../../utils/redis");

/**
 * 获取课程列表
 * GET /admin/courses
 * @query { limit, offset }
 * @return 课程列表
 */
router.get("/", async function (req, res, next) {
  // 处理异常 try catch
  try {
    // 课程的分页查询
    const query = req.query;
    // 当前页码 默认 1
    const currentPage = Math.abs(+query.currentPage) || 1;
    // 每页多少条数据 默认 10
    const pageSize = Math.abs(+query.pageSize) || 10;
    // 偏移量
    const offset = (currentPage - 1) * pageSize;

    const condition = {
      ...getCondition(),
      where: {},
      order: [
        ["id", "DESC"],
        // ['createdAt', 'DESC']
      ],
      limit: pageSize,
      offset,
    };
    // 标题的模糊查询
    if (query.categoryId) {
      condition.where.categoryId = query.categoryId;
    }

    if (query.userId) {
      condition.where.userId = query.userId;
    }

    if (query.name) {
      condition.where.name = {
        [Op.like]: `%${query.name}%`,
      };
    }

    if (query.recommended) {
      condition.where.recommended = query.recommended === "true";
    }

    if (query.introductory) {
      condition.where.introductory = query.introductory === "true";
    }

    // 查询所有课程
    // 注意：在一对多的关联查询中，findAndCountAll中的count统计数会出错，需要在查询条件中加入 distinct: true 进行去重
    const { rows, count } = await Course.findAndCountAll(condition);
    // 成功状态码 默认200 正确响应了
    success(res, "查询课程列表成功", {
      courses: rows,
      pagination: {
        currentPage,
        pageSize,
        total: count,
      },
    });
  } catch (error) {
    failure(res, error);
  }
});
/**
 * 获取课程详情
 * GET /admin/courses/:id
 * @params id 课程id
 * @return 课程详情
 */
router.get("/:id", async function (req, res, next) {
  // 处理异常 try catch
  try {
    const course = await getCourse(req);
    // 成功状态码 默认200
    success(res, "查询课程详情成功", { course });
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 新增课程
 * POST /admin/courses
 * @body title 标题
 * @body content 内容
 * @return
 */
router.post("/", async function (req, res, next) {
  // 处理异常 try catch
  try {
    const body = filterBody(req);
    // 获取并设置当前登录的用户ID
    body.userId = req.user.id;

    const course = await Course.create(body);
    await clearCache();
    // 成功状态码 201 正确响应了，并创建了新的资源
    success(res, "新增课程成功", course, 201);
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 删除课程
 * DELETE /admin/courses/:id
 * @params id 课程id
 * @return
 */
router.delete("/:id", async function (req, res, next) {
  // 处理异常 try catch
  try {
    const course = await getCourse(req);

    const count = await Chapter.count({
      where: {
        courseId: req.params.id,
      },
    });

    if (count > 0) {
      throw new Conflict("该课程下有章节，无法删除");
    }

    await course.destroy();
    await clearCache(course);

    success(res, "删除课程成功");
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 更新课程
 * PUT /admin/courses/:id
 * @params id 课程id
 * @body title 标题
 * @body content 内容
 * @return 课程详情
 */
router.put("/:id", async function (req, res, next) {
  // 处理异常 try catch
  try {
    const course = await getCourse(req);
    // 白名单过滤
    const body = filterBody(req);

    await course.update(body);
    await clearCache(course);

    success(res, "更新课程成功", { course });
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 公共方法: 查询当前课程
 */
async function getCourse(req) {
  // 获取课程ID
  const { id } = req.params;
  // 关联条件
  const condition = getCondition();
  // 查询课程
  const course = await Course.findByPk(id, condition);
  // 课程不存在 抛出异常
  if (!course) {
    throw new NotFound(`ID: ${id}的课程不存在`);
  }
  // 课程存在
  return course;
}

/**
 * 公共方法: 关联条件
 * @returns {{include: [{as: string, model, attributes: string[]}], attributes: {exclude: string[]}}}
 */
function getCondition() {
  return {
    // distinct: true,// 去重
    // 排除查询字段
    attributes: { exclude: ["CategoryId", "UserId"] },
    include: [
      {
        model: Category,
        as: "category",
        attributes: ["id", "name"],
      },
      {
        model: User,
        as: "user",
        attributes: ["id", "username", "avatar"],
      },
    ],
  };
}

/**
 * 公共方法：白名单过滤
 * @param req
 * @returns {{image: *, name, introductory: (boolean|*), categoryId: (number|*), content, recommended: (boolean|*)}}
 */
function filterBody(req) {
  return {
    categoryId: req.body.categoryId,
    // userId: req.body.userId, // 登录时，用户id由token解析获得
    name: req.body.name,
    image: req.body.image,
    recommended: req.body.recommended,
    introductory: req.body.introductory,
    content: req.body.content,
    free: req.body.free,
  };
}

/**
 * 清除缓存
 * @param course
 * @returns {Promise<void>}
 */
async function clearCache(course = null) {
  let keys = await getKeysByPattern("courses:*");
  if (keys.length !== 0) {
    await delKey(keys);
  }

  if (course) {
    await delKey(`course:${course.id}`);
  }
}

module.exports = router;
